package server

import (
	"accx/appFramework/m_config"
	"errors"
	"net/http"
	"time"

	"github.com/cihub/seelog"
	"golang.org/x/net/http2"
	"golang.org/x/net/http2/h2c"
	"golang.org/x/sync/errgroup"
)

type HttpServer struct {
	server http.Server
	g      *errgroup.Group
}

type Http2Server struct {
	server http.Server
	g      *errgroup.Group
}

func NewHttpServer() *HttpServer {
	return new(HttpServer)
}

func NewHttp2Server() *Http2Server {
	return new(Http2Server)
}

func (s *HttpServer) Initialize(data ...interface{}) error {
	group, ok := data[0].(*errgroup.Group)
	if !ok {
		return errors.New("initialize HttpServer failed: error data[0]")
	}
	appConfig, ok := data[1].(*m_config.AppConfig)
	if !ok {
		return errors.New("initialize HttpServer failed: error data[1]")
	}
	configIndex, ok := data[2].(int)
	if !ok {
		return errors.New("initialize HttpServer failed: error data[2]")
	}

	seelog.Debug(configIndex, appConfig)

	s.g = group

	serverConfig := appConfig.Server[configIndex]
	s.server.Addr = serverConfig.IP + ":" + serverConfig.Port
	s.server.ReadTimeout = time.Duration(serverConfig.ReadTimeout) * time.Second
	s.server.WriteTimeout = time.Duration(serverConfig.WriteTimeout) * time.Second
	return nil
}

func (s *HttpServer) RegisterHandler(r http.Handler) {
	s.server.Handler = r
}

func (s *HttpServer) Start() {
	seelog.Debug(s.server.Addr, " start...")
	s.g.Go(func() error {
		return s.server.ListenAndServe()
	})
}

func (s *Http2Server) Initialize(data ...interface{}) error {
	group, ok := data[0].(*errgroup.Group)
	if !ok {
		return errors.New("Initialize Http2Server failed: error data[0]")
	}
	appConfig, ok := data[1].(*m_config.AppConfig)
	if !ok {
		return errors.New("Initialize Http2Server failed: error data[1]")
	}
	configIndex, ok := data[2].(int)
	if !ok {
		return errors.New("Initialize Http2Server failed: error data[2]")
	}

	seelog.Debug(configIndex, appConfig)

	s.g = group

	serverConfig := appConfig.Server[configIndex]
	s.server.Addr = serverConfig.IP + ":" + serverConfig.Port
	s.server.ReadTimeout = time.Duration(serverConfig.ReadTimeout) * time.Second
	s.server.WriteTimeout = time.Duration(serverConfig.WriteTimeout) * time.Second
	return nil
}

func (s *Http2Server) RegisterHandler(r http.Handler) {
	h2s := &http2.Server{}
	s.server.Handler = h2c.NewHandler(r, h2s)
}

func (s *Http2Server) Start() {
	seelog.Debug(s.server.Addr, " start...")
	s.g.Go(func() error {
		return s.server.ListenAndServe()
	})
}
